// 
//  Copyright © 2008, 2009 Jiří Zárevúcky <zarevucky.jiri@gmail.com>
// 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as
//  published by the Free Software Foundation, either version 3 of the
//  License, or (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
// 
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
// 
// 

using System;
using System.IO;
using System.Net.Sockets;
using System.Collections.Generic;

using Galaxium.Protocol.Xmpp.Library.Utility;

namespace Galaxium.Protocol.Xmpp.Library.Xml
{
	public class StreamParser: Parser
	{
		private uint _depth = 0;
		private Element _current;
		
		public event EventHandler<ElementEventArgs> StreamStarted;
		public event EventHandler<ElementEventArgs> ElementParsed;
		public event EventHandler StreamEnded;
		
		public StreamParser ()
			:base ()
		{
			ElementStartEvent += HandleElementStart;
			ElementEndEvent += HandleElementEnd;
			TextNodeEvent += HandleTextNode;
		}
		
		public new void Restart ()
		{
			base.Restart ();
			_depth = 0;
			_current = null;
		}
		
		private void OnStreamStarted (Element elm)
		{
			if (StreamStarted != null)
				StreamStarted (this, new ElementEventArgs (elm));
		}
		
		private void OnElementParsed (Element elm)
		{
			if (ElementParsed != null)
				ElementParsed (this, new ElementEventArgs (elm));
		}
		
		private void OnStreamEnded ()
		{
			if (StreamEnded != null)
				StreamEnded (this, EventArgs.Empty);
		}
	
		private void HandleElementStart (string name, Dictionary<string, string> attribs)
		{
			var index = name.IndexOf (':');
			var prefix = index >= 0 ? name.Substring (0, index) : null;
			var sname  = index >= 0 ? name.Substring (index + 1) : name;
			
			var elm = new Element (prefix, sname, attribs);
			
			if (_depth > 1)
				_current.AppendChild (elm);
			else if (_depth == 0)
				OnStreamStarted (elm); 
			
			_current = elm;
			_depth ++;
		}
		private void HandleElementEnd (string name)
		{
			switch (-- _depth) {
				case 0:
					OnStreamEnded ();
					break;
				case 1:
					Console.WriteLine ("### Decoded element: " + Serializer.Serialize (_current));
					OnElementParsed (_current);
					_current = null;
					break;
				default:
					_current = _current.Parent;
					break;
			}
		}
		private void HandleTextNode (string text)
		{
			if (_current != null)
				_current.AppendText (text);
		}
	}
}